
package com.trydofor.id.lazy;

import java.util.List;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

import javax.annotation.Nonnull;
import javax.annotation.concurrent.ThreadSafe;

import com.trydofor.id.core.A9DU;
import com.trydofor.id.core.A9Loader;
import com.trydofor.id.core.A9Maker;
import com.trydofor.id.core.ApiExceptions;

/**
 * @param <T> the A9DU to make.
 * @author : Shi Rongjiu (www.trydofor.com)
 * @see LazyEntryA9cq
 */
@ThreadSafe
public class LazyA9Maker<T extends A9DU> implements A9Maker<T> {
    
    private final LazyEntryA9cq<T> lazycq;
    
    /**
     * an atomic lazy A9Maker with default ThreadFactory.
     * 
     * @param loader @Nonnull the loader.
     * @param worker the worker
     * @param latch the latch.
     * @throws NullPointerException if loader is null
     * @see Executors#defaultThreadFactory()
     */
    public LazyA9Maker(@Nonnull A9Loader<List<T>> loader, int latch) {
        this(loader, latch, Executors.defaultThreadFactory());
    }
    
    /**
     * an atomic lazy A9Maker.
     * 
     * @param loader @Nonnull the loader.
     * @param worker the worker
     * @param latch the latch.
     * @param factory @Nonnull the thread factory
     * @throws NullPointerException if loader or factory is null
     */
    public LazyA9Maker(@Nonnull A9Loader<List<T>> loader, int latch,
            @Nonnull ThreadFactory factory) {
        ApiExceptions.checkNullPointer(loader);
        ApiExceptions.checkNullPointer(factory);
        this.lazycq = new LazyEntryA9cq<T>(loader, latch, factory);
    }
    
    /**
     * {@inheritDoc}
     */
    public T make() {
        return lazycq.next();
    }
    
    /**
     * {@inheritDoc}
     */
    public T make(long timeout, TimeUnit unit) throws InterruptedException, TimeoutException {
        return lazycq.next(timeout, unit);
    }
}
